package com.gzz.orchid.context.domain.inventory;

import com.gzz.orchid.common.core.support.ContextBeanRegistry;
import com.gzz.orchid.common.core.tuple.OrderNo;
import com.gzz.orchid.context.domain.inventory.entity.*;
import com.gzz.orchid.context.infrastructure.definition.Status;
import com.gzz.orchid.context.infrastructure.support.serial.*;

import java.time.LocalDateTime;

/**
 * 库存单据工厂
 *
 * @author higmd
 */
public class InventoryFactory {
    private final DeliverySerialNoGenerator deliverySerialNoGenerator;
    private final PurchaseSerialNoGenerator purchaseSerialNoGenerator;
    private final ReceivedSerialNoGenerator receivedSerialNoGenerator;
    private final ReturnSerialNoGenerator returnSerialNoGenerator;
    private final ScrapSerialNoGenerator scrapSerialNoGenerator;

    private final StocktakeSerialNoGenerator stocktakeSerialNoGenerator;
    private final TransferSerialNoGenerator transferSerialNoGenerator;

    public InventoryFactory() {
        deliverySerialNoGenerator = ContextBeanRegistry.getBean(DeliverySerialNoGenerator.class);
        purchaseSerialNoGenerator = ContextBeanRegistry.getBean(PurchaseSerialNoGenerator.class);
        receivedSerialNoGenerator = ContextBeanRegistry.getBean(ReceivedSerialNoGenerator.class);
        returnSerialNoGenerator = ContextBeanRegistry.getBean(ReturnSerialNoGenerator.class);
        scrapSerialNoGenerator = ContextBeanRegistry.getBean(ScrapSerialNoGenerator.class);
        stocktakeSerialNoGenerator = ContextBeanRegistry.getBean(StocktakeSerialNoGenerator.class);
        transferSerialNoGenerator = ContextBeanRegistry.getBean(TransferSerialNoGenerator.class);
    }

    public static InventoryFactory builder() {
        return SingletonHolder.INSTANCE;
    }

    /**
     * 创建配货单
     */
    public DeliveryDo buildDeliveryOrder() {
        var deliveryOrder = new DeliveryDo();
        deliveryOrder.setNo(new OrderNo(deliverySerialNoGenerator.generateSerialNo()));
        deliveryOrder.setTimeAt(LocalDateTime.now());
        deliveryOrder.setStatus(Status.CREATED);
        return deliveryOrder;
    }

    /**
     * 创建采购单
     */
    public PurchaseDo buildPurchaseOrder() {
        var purchaseOrder = new PurchaseDo();
        purchaseOrder.setNo(new OrderNo(purchaseSerialNoGenerator.generateSerialNo()));
        purchaseOrder.setTimeAt(LocalDateTime.now());
        purchaseOrder.setStatus(Status.CREATED);
        return purchaseOrder;
    }

    /**
     * 创建收货单
     */
    public ReceivedDo buildReceivedOrder() {
        var receivedOrder = new ReceivedDo();
        receivedOrder.setNo(new OrderNo(receivedSerialNoGenerator.generateSerialNo()));
        receivedOrder.setTimeAt(LocalDateTime.now());
        receivedOrder.setStatus(Status.CREATED);
        return receivedOrder;
    }

    /**
     * 创建退货单
     */
    public ReturnDo buildReturnOrder() {
        var returnOrder = new ReturnDo();
        returnOrder.setNo(new OrderNo(returnSerialNoGenerator.generateSerialNo()));
        returnOrder.setTimeAt(LocalDateTime.now());
        returnOrder.setStatus(Status.CREATED);
        return returnOrder;
    }

    /**
     * 创建报废单
     */
    public ScrapDo buildScrapOrder() {
        var scrapOrder = new ScrapDo();
        scrapOrder.setNo(new OrderNo(scrapSerialNoGenerator.generateSerialNo()));
        scrapOrder.setTimeAt(LocalDateTime.now());
        scrapOrder.setStatus(Status.CREATED);
        return scrapOrder;
    }

    /**
     * 创建盘点单
     */
    public StocktakeDo buildStocktakeOrder() {
        var stocktakeOrder = new StocktakeDo();
        stocktakeOrder.setNo(new OrderNo(stocktakeSerialNoGenerator.generateSerialNo()));
        stocktakeOrder.setTimeAt(LocalDateTime.now());
        stocktakeOrder.setStatus(Status.CREATED);
        return stocktakeOrder;
    }

    /**
     * 创建调拨单
     */
    public TransferDo buildTransferOrder() {
        var transferOrder = new TransferDo();
        transferOrder.setNo(new OrderNo(transferSerialNoGenerator.generateSerialNo()));
        transferOrder.setTimeAt(LocalDateTime.now());
        transferOrder.setStatus(Status.CREATED);
        return transferOrder;
    }

    private static class SingletonHolder {
        private static final InventoryFactory INSTANCE = new InventoryFactory();
    }
}
